package jusda.caa.minio.utils;

import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import jusda.caa.minio.entity.FileAttributeDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class MinioUtils {

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.accesskey}")
    private String accessKey;

    @Value("${minio.secretkey}")
    private String secretKey;

//    private static MinioClient minioClient=null;

//    private static String minio_bucketName="test";

    /**
     * 获取minio客户端
     *
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     */
    private MinioClient getClient() throws InvalidPortException, InvalidEndpointException {
        MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);
        long time = 5 * 60 * 1000;
        minioClient.setTimeout(time, time, time);
        return minioClient;
    }

    /**
     * 判断bucket是否存在
     *
     * @param bucketName 文件桶
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public boolean bucketExists(String bucketName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getClient().bucketExists(bucketName);
    }

    /**
     * 上传文件
     *
     * @param bucketName     文件桶
     * @param targetName     文件名称
     * @param stream         上传文件流
     * @param sourceFileName 源文件名称
     * @param description    源文件描述
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws XmlPullParserException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws InvalidArgumentException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws InsufficientDataException
     * @throws ErrorResponseException
     */
    public void uploadFile(String bucketName, String targetName, InputStream stream, String sourceFileName, String description) throws InvalidPortException, InvalidEndpointException, IOException, XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, InvalidArgumentException, InternalException, NoResponseException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException {
        HashMap<String, String> map = new HashMap<>();
        map.put("sourceFileName", sourceFileName);
        map.put("description", description);
        MinioClient client = getClient();
        client.putObject(bucketName, targetName, stream, null, map, null, null);
    }

    /**
     * 获取文件访问链接
     *
     * @param bucketName 文件桶
     * @param targetName 文件名称
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public String getFileUrl(String bucketName, String targetName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getClient().getObjectUrl(bucketName, targetName);
    }


    /**
     * 获取文件流
     *
     * @param bucketName 文件桶
     * @param targetName 文件名称
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InvalidArgumentException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public InputStream getFile(String bucketName, String targetName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidArgumentException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getClient().getObject(bucketName, targetName);
    }

    /**
     * 删除文件
     *
     * @param bucketName 文件桶
     * @param targetName 文件名称
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InvalidArgumentException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public void deleteFile(String bucketName, String targetName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidArgumentException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        getClient().removeObject(bucketName, targetName);
    }

    /**
     * 批量删除
     * @param bucketName 文件桶名称
     * @param targetNames 文件列表
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InvalidArgumentException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public void deleteFiles(String bucketName, List<String> targetNames) throws InvalidPortException, InvalidEndpointException {
        Iterable<Result<DeleteError>> results = getClient().removeObjects(bucketName, targetNames);
    }

    /**
     * 复制文件
     *
     * @param bucketName     现文件所在桶
     * @param targetName     现文件名称
     * @param destBucketName 复制目标文件所在桶
     * @param destTargetName 复制目标文件名称
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws XmlPullParserException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws InvalidArgumentException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws InsufficientDataException
     * @throws ErrorResponseException
     */
    public void copyFile(String bucketName, String targetName, String destBucketName, String destTargetName) throws InvalidPortException, InvalidEndpointException, IOException, XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, InvalidArgumentException, InternalException, NoResponseException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException {
        getClient().copyObject(bucketName, targetName, destBucketName, destTargetName);
    }

    /**
     * 文件详细
     *
     * @param bucketName
     * @param targetName
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws XmlPullParserException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws InvalidArgumentException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws InsufficientDataException
     * @throws ErrorResponseException
     */
    public FileAttributeDTO fileDetail(String bucketName, String targetName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        ObjectStat objectStat = getClient().statObject(bucketName, targetName);
        FileAttributeDTO fileAttributeDTO = new FileAttributeDTO();
        fileAttributeDTO.setBucketName(objectStat.bucketName());
        fileAttributeDTO.setName(objectStat.name());
        fileAttributeDTO.setContentType(objectStat.contentType());
        fileAttributeDTO.setCreatedTime(objectStat.createdTime().getTime());
        fileAttributeDTO.setEtag(objectStat.etag());
        fileAttributeDTO.setLength(objectStat.length());
        fileAttributeDTO.setHearder(objectStat.httpHeaders());
        return fileAttributeDTO;
    }

    /**
     * 临时下载文件链接
     *
     * @param bucketName 文件桶
     * @param targetName 文件名
     * @param expires    过期时间 单位秒
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InvalidExpiresRangeException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public String temporaryDownloadURL(String bucketName, String targetName, Integer expires) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidExpiresRangeException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return temporaryDownloadURL(bucketName,targetName,expires,null);
    }

    /**
     * 临时下载文件链接
     * @param bucketName 文件桶
     * @param targetName 文件名
     * @param expires    过期时间 单位秒
     * @param requestHeader 请求头部
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InvalidExpiresRangeException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public String temporaryDownloadURL(String bucketName, String targetName, Integer expires, Map<String, String> requestHeader) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidExpiresRangeException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getClient().presignedGetObject(bucketName, targetName, expires,requestHeader);
    }

    /**
     * 临时上传文件链接 注:生成的链接需要使用 HTTP PUT方式
     *
     * @param bucketName 文件桶
     * @param targetName 文件名
     * @param expires    过期时间 单位秒
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InvalidExpiresRangeException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public String temporaryUploadURL(String bucketName, String targetName, Integer expires) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidExpiresRangeException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getClient().presignedPutObject(bucketName, targetName, expires);
    }

    /**
     * 创建bucket
     * @param bucketName 文件桶名称
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws ErrorResponseException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws InternalException
     * @throws RegionConflictException
     */
    public void createBucket(String bucketName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ErrorResponseException, NoResponseException, InvalidBucketNameException, XmlPullParserException, InternalException, RegionConflictException {
        getClient().makeBucket(bucketName);
    }

    /**
     * 现有的bucket列表
     * @return
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public List<Bucket> bucketList() throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getClient().listBuckets();
    }

    /**
     * 删除bucket
     * @param bucketName 文件桶名称
     * @throws InvalidPortException
     * @throws InvalidEndpointException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws InternalException
     * @throws NoResponseException
     * @throws InvalidBucketNameException
     * @throws XmlPullParserException
     * @throws ErrorResponseException
     */
    public void deleteBucket(String bucketName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        getClient().removeBucket(bucketName);
    }
}
